package se.haaga.jsupervision.gui.linux;

import java.awt.Dimension;
import java.beans.PropertyVetoException;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.BoxLayout;
import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

import se.haaga.jsupervision.monitor.linux.LinuxMonitor;
import se.haaga.jsupervision.monitor.linux.LinuxMonitor.LinuxVariables;
import se.haaga.jsupervision.monitor.linux.LinuxMonitors;
import se.haaga.jsupervision.util.Translator;
import se.haaga.jsupervision.util.UserVariables;

public class LinuxMonitorTab extends JDesktopPane {

	private static final long serialVersionUID = -2809404184826437026L;
	private final String connectionName;
    private JInternalFrame jifMemory = null;
    private JInternalFrame jifSysinfo = null;
    private JInternalFrame jifCPUinfo = null;
    private JInternalFrame jifDriveInfo = null;
	private JPanel driveContainer = null;
	private JPanel cpuContainer = null;
	private JPanel distContainer = null;
	private JPanel memContainer = null;
	
	public LinuxMonitorTab(String connectionName) {
		super();
		this.connectionName = connectionName;
		initGUI();
	}
	
	private void initGUI() {
		initSysinfoFrame();
		initMemoryFrame();
		initCPUFrame();
		initDriveFrame();
		
		addSysinfoData();
		addMemoryData();
		addCPUData();
		addDriveInfoData();
		
		jifSysinfo.setLocation(0, 0);
		jifMemory.setLocation(jifSysinfo.getWidth() + 5, 0);
		jifCPUinfo.setLocation(jifSysinfo.getWidth() + 5, jifMemory.getHeight() + 5);
		jifDriveInfo.setLocation(0, jifSysinfo.getHeight() + 5);
		
		jifSysinfo.setVisible(true);
		jifMemory.setVisible(true);
		jifCPUinfo.setVisible(true);
		jifDriveInfo.setVisible(true);
		
		try {
			jifSysinfo.setSelected(true);
		} catch (PropertyVetoException e) {
			System.err.println(e);
		}
		new Timer().schedule(new UpdateTimer(), UserVariables.updateSysinfoIntervalInSeconds*1000, UserVariables.updateSysinfoIntervalInSeconds*1000);
	}

	private void initDriveFrame() {
		driveContainer = new JPanel();
		driveContainer.setLayout(new BoxLayout(driveContainer, BoxLayout.Y_AXIS)); 	
		jifDriveInfo = new JInternalFrame(Translator.MONITOR_LINUX_DRIVE_TITLE.getTranslation(), false, false, false);
        add(jifDriveInfo);
	}
	
	private void addDriveInfoData() {
		LinuxMonitor lm = LinuxMonitors.getInstance().getLinuxMonitor(connectionName);
		if (lm != null) {
			Map<LinuxVariables, String> variables = lm.getDriveInfo();
			String[] splitted = variables.get(LinuxVariables.DRIVE_SPACE).split("@");
			for (int i = 0; i < splitted.length; i++) {
				String[] tmp = splitted[i].split(";");
				Integer used = Integer.parseInt(tmp[0]);
				Integer available = Integer.parseInt(tmp[1]);
				String percentage = tmp[2];
				String mount = tmp[3];
				double total = (used / 1000) + (available / 1000);
				JProgressBar jbDrive = new JProgressBar(0, used + available);
				jbDrive.setValue(used);
				jbDrive.setStringPainted(true);
				jbDrive.setString(mount + ": " + (float) used / 1000 + "G/" + total + "G (" + percentage + ")");
				driveContainer.add(jbDrive);
			}
		}    
		jifDriveInfo.add(driveContainer);
		jifDriveInfo.pack();
		jifDriveInfo.setSize(new Dimension(jifDriveInfo.getWidth() + 5, jifDriveInfo.getHeight() + 10));
		jifDriveInfo.repaint();
		jifDriveInfo.validate();
	}
	
	private void removeOldDriveInfoData() {
		jifDriveInfo.remove(driveContainer);
		driveContainer = new JPanel();
		driveContainer.setLayout(new BoxLayout(driveContainer, BoxLayout.Y_AXIS));
	}

	private void initCPUFrame() {
		cpuContainer = new JPanel();
		cpuContainer.setLayout(new BoxLayout(cpuContainer, BoxLayout.Y_AXIS));
		
		jifCPUinfo = new JInternalFrame(Translator.MONITOR_LINUX_CPU_TITLE.getTranslation(), false, false, false);
        add(jifCPUinfo);
	}
	
	private void addCPUData() {
		LinuxMonitor lm = LinuxMonitors.getInstance().getLinuxMonitor(connectionName);
		if (lm != null) {
			Map<LinuxVariables, String> variables = lm.getCPULoad();
			int totalCPUs = Integer.parseInt(variables.get(LinuxVariables.TOTAL_CPUS_FOUND));
			String[] splitted = variables.get(LinuxVariables.CPU_LOAD).split("@");
			for (int i = 0; i < totalCPUs; i++) {
				String[] tmp = splitted[i].split(";");
				JProgressBar jbCPU = new JProgressBar(0, 100);
				jbCPU.setValue(Integer.parseInt(tmp[1]));
				jbCPU.setStringPainted(true);
				jbCPU.setString("CPU " + i + ": " + tmp[1] + " %");
				cpuContainer.add(jbCPU);
			}
		}
        
		jifCPUinfo.add(cpuContainer);
		jifCPUinfo.pack();
		jifCPUinfo.setSize(new Dimension(jifCPUinfo.getWidth() + 5, jifCPUinfo.getHeight() + 10));
		jifCPUinfo.repaint();
		jifCPUinfo.validate();
	}
	
	private void removeOldCPUData() {
		jifCPUinfo.remove(cpuContainer);
		cpuContainer = new JPanel();
		cpuContainer.setLayout(new BoxLayout(cpuContainer, BoxLayout.Y_AXIS));
	}

	private void initSysinfoFrame() {
		distContainer = new JPanel();
		distContainer.setLayout(new BoxLayout(distContainer, BoxLayout.Y_AXIS)); 
		jifSysinfo = new JInternalFrame(Translator.MONITOR_LINUX_SYSINFO_TITLE.getTranslation(), false, false, false);
        add(jifSysinfo);
	}
	
	private void addSysinfoData() {
		String id = "";
		String release = "";
		String codename = "";
		String description = "";
		String kernelVersion = "";
		String uptime = "";
		
		LinuxMonitor lm = LinuxMonitors.getInstance().getLinuxMonitor(connectionName);
		if (lm != null) {
			Map<LinuxVariables, String> variables = lm.getSystemInformation();
			id = variables.get(LinuxVariables.DISTRIBUTION_ID);
			release = variables.get(LinuxVariables.DISTRIBUTION_RELEASE);
			codename = variables.get(LinuxVariables.DISTRIBUTION_CODENAME);
			description = variables.get(LinuxVariables.DISTRIBUTION_DESCRIPTION);
			kernelVersion = variables.get(LinuxVariables.KERNEL_VERSION);
			uptime = variables.get(LinuxVariables.UPTIME);
		}
		JLabel jlId = new JLabel(Translator.MONITOR_LINUX_SYSINFO_ID.getTranslation() + ": " + id);
		JLabel jlRelease = new JLabel(Translator.MONITOR_LINUX_SYSINFO_RELEASE.getTranslation() + ": " + release);
		JLabel jlCodename = new JLabel(Translator.MONITOR_LINUX_SYSINFO_CODENAME.getTranslation() + ": " + codename);
		JLabel jlDescription = new JLabel(Translator.MONITOR_LINUX_SYSINFO_DESCRIPTION.getTranslation() + ": " + description);
		JLabel jlKernelVersion = new JLabel(Translator.MONITOR_LINUX_SYSINFO_KERNEL_VERSION.getTranslation() + ": " + kernelVersion);
		JLabel jlUptime = new JLabel(Translator.MONITOR_LINUX_SYSINFO_UPTIME.getTranslation() + ": " + uptime);
		
        distContainer.add(jlId);
        distContainer.add(jlRelease);
        distContainer.add(jlCodename);
        distContainer.add(jlDescription);
        distContainer.add(jlKernelVersion);
        distContainer.add(jlUptime);
        
        jifSysinfo.add(distContainer);
        jifSysinfo.pack();
        jifSysinfo.setSize(new Dimension(jifSysinfo.getWidth() + 5, jifSysinfo.getHeight() + 10));
        jifSysinfo.repaint();
        jifSysinfo.validate();
	}
	
	private void removeOldSysinfoData() {
		jifSysinfo.remove(distContainer);
		distContainer = new JPanel();
		distContainer.setLayout(new BoxLayout(distContainer, BoxLayout.Y_AXIS));
	}

	private void initMemoryFrame() {
		memContainer = new JPanel();
		memContainer.setLayout(new BoxLayout(memContainer, BoxLayout.Y_AXIS));
		jifMemory = new JInternalFrame(Translator.MONITOR_LINUX_MEMORY_TITLE.getTranslation(), false, false, false);
        add(jifMemory);
	}
	
	private void addMemoryData() {
		Integer totalRam = 1;
		Integer usedRam = 1;		
		Integer totalSwap = 1;
		Integer usedSwap = 1;
		LinuxMonitor lm = LinuxMonitors.getInstance().getLinuxMonitor(connectionName);
		if (lm != null) {
			Map<LinuxVariables, Integer> variables = lm.getMemoryStatus();
			totalRam = variables.get(LinuxVariables.SYS_MEM_TOTAL);
			usedRam = variables.get(LinuxVariables.SYS_MEM_AVAILABLE);
			totalSwap = variables.get(LinuxVariables.SWAP_TOTAL);
			usedSwap = variables.get(LinuxVariables.SWAP_AVAILABLE);
		}
		int percent = getPercentFromTotal(usedRam, totalRam);
		JProgressBar jpbRam = new JProgressBar(0, totalRam);
		jpbRam.setValue(usedRam);
		jpbRam.setStringPainted(true);
		jpbRam.setString("Psysical usage: " + usedRam + " / " + totalRam + " MB (" + percent + " %)");
		percent = getPercentFromTotal(usedSwap, totalSwap);
		JProgressBar jpbSwap = new JProgressBar(0, totalSwap);
		jpbSwap.setValue(usedSwap);
		jpbSwap.setStringPainted(true);
		jpbSwap.setString("Swap usage: " + usedSwap + " / " + totalSwap + " MB (" + percent + " %)");
        memContainer.add(jpbRam);
        memContainer.add(jpbSwap);
        jifMemory.add(memContainer);
        jifMemory.pack();
        jifMemory.setSize(new Dimension(jifMemory.getWidth() + 5, jifMemory.getHeight() + 10));
        jifMemory.repaint();
        jifMemory.validate();
	}
	
	private void removeOldMemoryData() {
		jifMemory.remove(memContainer);
		memContainer = new JPanel();
		memContainer.setLayout(new BoxLayout(memContainer, BoxLayout.Y_AXIS));
	}
	
	private static int getPercentFromTotal(int subtotal, int total) {
	    return (int) (((float) subtotal / (float) total) * 100);
	}

	public String getConnectionName() {
		return connectionName;
	}
	
	class UpdateTimer extends TimerTask {
		@Override
		public void run() {
			removeOldSysinfoData();
			addSysinfoData();
			removeOldMemoryData();
			addMemoryData();
			removeOldCPUData();
			addCPUData();
			removeOldDriveInfoData();
			addDriveInfoData();
		}
	}

}
